/**
 * @file Tetrobox.java
 * 
 *   This is a class file representing a single box on a 'tetris' grid.
 *   This class provides no control logic, except to appear or disappear.
 */
package sprite;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Point;

public class Tetrobox extends Sprite{
	
	/**
	 *  Border Width Ratios
	 */
	private double border_horizontal = 0.05;
	private double border_vertical = 0.05;
	
	/**
	 * Box Shadow Polygons
	 */
    private Polygon shadow_top = null;
    private Polygon shadow_left = null;
    private Polygon shadow_right = null;
    private Polygon shadow_bottom = null;
    
    /**
     * Colors of the box and the box shadows
     */
    private Color color_main;
    private Color color_sideOne;
    private Color color_sideTwo;
    
    /**
     * The actual width and height of the border surrounding the box
     * leaving room for box shadows
     */
    private int borderWidth;
	  private int borderHeight;
		
	/**
	 * Points defining where the intersections of polygons are, relative to the base
	 * point of the sprite.
	 */
	private Point outer_top_left;
	private Point inner_top_left;
	
	private Point outer_top_right;
	private Point inner_top_right;
	
	private Point outer_bottom_right;
	private Point inner_bottom_right;
	
	private Point outer_bottom_left;
	private Point inner_bottom_left;
	
	/**
	 * Inidicates whether this tetrimino is visibile 
	 * (and, therefore, if it exists)
	 */
    private boolean visible;
    
    /**
     * Creates a new tetroox
     * 
     * @param x
     *   The x coordinate of the tetrobox on the tetris grid
     * @param y
     *   The y coordinate of the tetrobox on the tetris grid
     * @param width
     *   The width of this tetrobox, in pixels
     * @param height
     *   The height of this tetrobox, in pixels
     */
    public Tetrobox(int x, int y, int width, int height) {
      super();

      this.setPointX(x); 
      this.setPointY(y);
      this.setWidth(width);
      this.setHeight(height);
      
      setVisible(false);
    }
    
    /**
     * Copy Constructor
     * 
     * @param t
     *   The tetrobox to be cloned
     */
    public Tetrobox(Tetrobox t) {
    
	    border_horizontal = t.border_horizontal;
	    border_vertical   = t.border_vertical;
	    
      shadow_top    = t.shadow_top;
      shadow_left   = t.shadow_left;
      shadow_right  = t.shadow_right;
      shadow_bottom = t.shadow_bottom;
    
      color_main    = t.color_main;
      color_sideOne = t.color_sideOne;
      color_sideTwo = t.color_sideTwo;
      
      borderWidth   = t.borderWidth;
	    borderHeight  = t.borderHeight;
		
	    outer_top_left      = t.outer_top_left;
	    inner_top_left      = t.inner_top_left;
	    outer_top_right     = t.outer_top_right;
	    inner_top_right     = t.inner_top_right;
	    outer_bottom_right  = t.outer_bottom_right;
	    inner_bottom_right  = t.inner_bottom_right;
	    outer_bottom_left   = t.outer_bottom_left;
	    inner_bottom_left   = t.inner_bottom_left;
	
      visible = t.visible;
    
    }
    
    /**
     * Creates a new tetroox
     * 
     * @param x
     *   The x coordinate of the tetrobox on the tetris grid
     * @param y
     *   The y coordinate of the tetrobox on the tetris grid
     * @param width
     *   The width of this tetrobox, in pixels
     * @param height
     *   The height of this tetrobox, in pixels
     * @param visible
     *   Set the visiblity of the new tetrobox
     */
    public Tetrobox(int x, int y, int width, int height, boolean visible) {
    
    
      this.setPointX(x); 
      this.setPointY(y);
      this.setWidth(width);
      this.setHeight(height);
      
      setVisible(visible);
    }
    
    /** 
     * Set the colors of the tetrobox and make it visible
     * 
     * @param main
     *   The main body color of the block
     * @param s1
     *   The shade color on the bottom and left of the block
     * @param s2
     *   The shade color on the top and right of the block
     */
	public void setColors(Color main, Color s1, Color s2) {
		
		// Assign colors
		this.color_main = main;
		this.color_sideOne = s1;
		this.color_sideTwo = s2;
		
		// Set visibility to true
		visible = true;
	}
	
	public void setVisible(boolean option) {
		
		this.visible = option;
	}
	
	public boolean isVisible() {
		
		return visible;
	}
	
	/**
	 *  Implements Sprite.draw()
	 */
	public Graphics draw(Graphics g, Point base) {
		
		if (visible) {
			
	      /**	
		   * Draw a square with a 5% shadow border
		   */
		  // Calculate Reference Points 
		  initReferencePoints(base);
		  
		  // Create essential polygons and rectangles
		  shadow_left = makeLeftShadow();
		  shadow_right = makeRightShadow();
		  shadow_top = makeTopShadow();
		  shadow_bottom = makeBottomShadow();
		  
	      // Now draw it!
		  g.setColor(color_sideOne);
		  g.fillPolygon(shadow_bottom);  
		  g.fillPolygon(shadow_left);
		  
		  g.setColor(color_sideTwo);
		  g.fillPolygon(shadow_top);
		  g.fillPolygon(shadow_right);
		 
		  g.setColor(color_main); 
		  g.fillRect(base.x + borderWidth, base.y + borderHeight, 
			  this.getWidth() - (borderWidth * 2), 
			  this.getHeight() - (borderHeight * 2)
			);
		}
		
		else {
		
		  g.setColor(Color.white);
		  g.drawRect(base.x, base.y, this.getWidth(), this.getHeight());
		}
		
		return g;
	}
	
	/**
	 * Set polygons for tetrobox based on parameters.
	 */
	private void initReferencePoints(Point base) {
		
		borderWidth = (int) border_horizontal * this.getWidth();
		borderHeight = (int) border_vertical * this.getHeight();
		
		if (borderWidth < 3) {
			
			borderWidth = 3;
		}
	    	
		if (borderHeight < 3) {
			
			borderHeight = 3;
		}
		
		outer_top_left = new Point(base.x, base.y);
		inner_top_left = new Point(base.x + borderWidth, base.y + borderHeight);
		
		outer_top_right = new Point(base.x + this.getWidth(), base.y);
		inner_top_right = new Point(base.x + (this.getWidth() - borderWidth), base.y + borderHeight);
		
		outer_bottom_right = new Point(base.x + this.getWidth(), base.y + this.getHeight());
		inner_bottom_right = new Point(base.x + (this.getWidth() - borderWidth), 
		    base.y + (this.getHeight() - borderHeight));
		
		outer_bottom_left  = new Point(base.x, base.y + this.getHeight());
		inner_bottom_left  = new Point(base.x + borderWidth, base.y + (this.getHeight() - borderHeight));
	}
	
    /**
     * Create Left Shadow Box
     */
	private Polygon makeLeftShadow() {
		
		  int[] sl_x = new int[4];
		  int[] sl_y = new int[4];
		  
		  // Outer Top Left
		  sl_x[0] = outer_top_left.x;
		  sl_y[0] = outer_top_left.y;
		  
		  // Inner Top Left
		  sl_x[1] = inner_top_left.x;
		  sl_y[1] = inner_top_left.y;
		  
		  // Inner Top Right
		  sl_x[2] = inner_bottom_left.x;
		  sl_y[2] = inner_bottom_left.y;
		  
		  // Outer Top Right
		  sl_x[3] = outer_bottom_left.x;
		  sl_y[3] = outer_bottom_left.y;
		  
		  return new Polygon(sl_x, sl_y, 4);
	}
	
	/**
	 * Create Top shadow polygon
	 *
	 * @return
	 *  A new Top Shadow polygon
	 */
	private Polygon makeTopShadow() {
		
		  int[] st_x = new int[4];
		  int[] st_y = new int[4];
		  
		  // Outer Top Left
		  st_x[0] = outer_top_left.x;
		  st_y[0] = outer_top_left.y;
		  
		  // Inner Top Left
		  st_x[1] = inner_top_left.x;
		  st_y[1] = inner_top_left.y;
		  
		  // Inner Top Right
		  st_x[2] = inner_top_right.x;
		  st_y[2] = inner_top_right.y;
		  
		  // Outer Top Right
		  st_x[3] = outer_top_right.x;
		  st_y[3] = outer_top_right.y;
		  
		  return new Polygon(st_x, st_y, 4);
	}
	
	/**
	 * Create a right shadow polygon
	 * 
	 * @return
	 *   A new right shadow polygon
	 */
	private Polygon makeRightShadow() {
		
		int[] sr_x = new int[4];
		int[] sr_y = new int[4];
		
		// Outer Top Right
		sr_x[0] = outer_top_right.x;
		sr_y[0] = outer_top_right.y;
		
		// Inner Top Right
		sr_x[1] = inner_top_right.x;
		sr_y[1] = inner_top_right.y;
		
		// Inner Bottom Right
		sr_x[2] = inner_bottom_right.x;
		sr_y[2] = inner_bottom_right.y;
		
		// Outer Bottom Right
		sr_x[3] = outer_bottom_right.x;
		sr_y[3] = outer_bottom_right.y;
		
		return new Polygon(sr_x, sr_y, 4);
		
	}
	
	/**
	 * Make a new bottom shadow polygon
	 * 
	 * @return
	 *   A new bottom shadow polygon
	 */
	private Polygon makeBottomShadow() {
		
		int[] sb_x = new int[4];
		int[] sb_y = new int[4];
		
		// Outer Bottom Left
		sb_x[0] = outer_bottom_left.x;
		sb_y[0] = outer_bottom_left.y;
		
		// Inner Bottom Left
		sb_x[1] = inner_bottom_left.x;
		sb_y[1] = inner_bottom_left.y;
		
		// Inner Bottom Right
		sb_x[2] = inner_bottom_right.x;
		sb_y[2] = inner_bottom_right.y;
		
		// Outer Bottom Right
		sb_x[3] = outer_bottom_right.x;
		sb_y[3] = outer_bottom_right.y;
		
		return new Polygon(sb_x, sb_y, 4);
	}
}
